package com.uniflow.service;

import com.uniflow.controller.AuthController;
import com.uniflow.entity.AuditLogs;
import com.uniflow.entity.Permission;
import com.uniflow.entity.User;
import com.uniflow.mapper.UserMapper;
import com.uniflow.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 认证服务类
 */
@Service
@Transactional
public class AuthService {
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private PermissionService permissionService;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Autowired
    private AuditLogService auditLogService;
    
    /**
     * 用户登录
     */
    public Map<String, Object> login(String username, String password) {
        try {
            // 执行认证
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(username, password)
            );
            
            // 获取用户信息
            User user = userMapper.selectByUsername(username);
            if (user == null) {
                user = userMapper.selectByEmail(username);
            }
            
            if (user == null) {
                throw new RuntimeException("用户不存在");
            }
            
            // 生成JWT令牌
            String accessToken = jwtUtil.generateToken(user.getUsername(), user.getId(), user.getOrgId());
            String refreshToken = jwtUtil.generateRefreshToken(user.getUsername(), user.getId());
            
            // 记录登录成功的审计日志
            recordAuditLog("LOGIN", "USER", user.getId(), 
                          "用户登录成功: " + username, "SUCCESS", user.getId());
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("accessToken", accessToken);
            result.put("refreshToken", refreshToken);
            result.put("tokenType", "Bearer");
            result.put("expiresIn", jwtUtil.getTokenRemainingTime(accessToken));
            
            // 获取用户详细信息（包含角色和权限）
            User userWithRoles = userMapper.selectWithRoles(user.getId());
            if (userWithRoles != null) {
                user = userWithRoles;
            }
            
            // 用户信息
            Map<String, Object> userInfo = new HashMap<>();
            userInfo.put("id", user.getId());
            userInfo.put("username", user.getUsername());
            userInfo.put("email", user.getEmail());
            userInfo.put("displayName", user.getDisplayName());
            userInfo.put("phone", user.getPhone());
            userInfo.put("orgId", user.getOrgId());
            userInfo.put("status", user.getStatus());
            
            // 添加角色和权限信息
            if (user.getRoles() != null) {
                List<String> roleNames = user.getRoles().stream()
                    .map(role -> role.getName())
                    .collect(java.util.stream.Collectors.toList());
                userInfo.put("roles", roleNames);
                
                // 收集所有权限
                List<Permission> userPermissions = permissionService.getUserPermissions(user.getId());
                List<String> permissions = userPermissions.stream()
                    .map(Permission::getCode)
                    .collect(Collectors.toList());
                userInfo.put("permissions", permissions);
            } else {
                userInfo.put("roles", new ArrayList<>());
                userInfo.put("permissions", new ArrayList<>());
            }
            
            result.put("user", userInfo);
            
            return result;
            
        } catch (AuthenticationException e) {
            // 记录登录失败的审计日志
            recordAuditLog("LOGIN", "USER", null, 
                          "用户登录失败: " + username + ", 原因: 用户名或密码错误", "FAILURE", null);
            throw new RuntimeException("用户名或密码错误");
        } catch (Exception e) {
            // 记录登录异常的审计日志
            recordAuditLog("LOGIN", "USER", null, 
                          "用户登录异常: " + username + ", 原因: " + e.getMessage(), "FAILURE", null);
            throw new RuntimeException("登录失败: " + e.getMessage());
        }
    }
    
    /**
     * 用户注册
     */
    public Map<String, Object> register(AuthController.RegisterRequest request) {
        // 检查用户名是否已存在
        if (userMapper.existsByUsername(request.getUsername(), null)) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 检查邮箱是否已存在
        if (userMapper.existsByEmail(request.getEmail(), null)) {
            throw new RuntimeException("邮箱已存在");
        }
        
        // 创建用户
        User user = new User();
        user.setId(UUID.randomUUID().toString().replace("-", ""));
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPasswordHash(passwordEncoder.encode(request.getPassword()));
        user.setDisplayName(request.getDisplayName());
        user.setPhone(request.getPhone());
        user.setOrgId(request.getOrgId());
        user.setStatus(1); // 默认启用
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        // 保存用户
        userMapper.insert(user);
        
        // 记录用户注册的审计日志
        recordAuditLog("REGISTER", "USER", user.getId(), 
                      "用户注册成功: " + user.getUsername(), "SUCCESS", user.getId());
        
        // 生成JWT令牌
        String accessToken = jwtUtil.generateToken(user.getUsername(), user.getId(), user.getOrgId());
        String refreshToken = jwtUtil.generateRefreshToken(user.getUsername(), user.getId());
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("accessToken", accessToken);
        result.put("refreshToken", refreshToken);
        result.put("tokenType", "Bearer");
        result.put("expiresIn", jwtUtil.getTokenRemainingTime(accessToken));
        
        // 获取用户详细信息（包含角色和权限）
        User userWithRoles = userMapper.selectWithRoles(user.getId());
        if (userWithRoles != null) {
            user = userWithRoles;
        }
        
        // 用户信息
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("email", user.getEmail());
        userInfo.put("displayName", user.getDisplayName());
        userInfo.put("phone", user.getPhone());
        userInfo.put("orgId", user.getOrgId());
        userInfo.put("status", user.getStatus());
        
        // 添加角色和权限信息
        if (user.getRoles() != null) {
            List<String> roleNames = user.getRoles().stream()
                .map(role -> role.getName())
                .collect(Collectors.toList());
            userInfo.put("roles", roleNames);
            
            // 收集所有权限
            List<Permission> userPermissions = permissionService.getUserPermissions(user.getId());
            List<String> permissions = userPermissions.stream()
                .map(Permission::getCode)
                .collect(Collectors.toList());
            userInfo.put("permissions", permissions);
        } else {
            userInfo.put("roles", new ArrayList<>());
            userInfo.put("permissions", new ArrayList<>());
        }
        
        result.put("user", userInfo);
        
        return result;
    }
    
    /**
     * 刷新令牌
     */
    public Map<String, Object> refreshToken(String refreshToken) {
        // 验证刷新令牌
        if (!jwtUtil.validateTokenFormat(refreshToken) || !jwtUtil.isRefreshToken(refreshToken)) {
            throw new RuntimeException("无效的刷新令牌");
        }
        
        // 从刷新令牌中获取用户信息
        String username = jwtUtil.getUsernameFromToken(refreshToken);
        String userId = jwtUtil.getUserIdFromToken(refreshToken);
        
        // 验证用户是否存在且状态正常
        User user = userMapper.selectById(userId);
        if (user == null || user.getStatus() != 1) {
            throw new RuntimeException("用户不存在或已被禁用");
        }
        
        // 生成新的访问令牌
        String newAccessToken = jwtUtil.generateToken(user.getUsername(), user.getId(), user.getOrgId());
        
        // 构建返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("accessToken", newAccessToken);
        result.put("refreshToken", refreshToken); // 刷新令牌保持不变
        result.put("tokenType", "Bearer");
        result.put("expiresIn", jwtUtil.getTokenRemainingTime(newAccessToken));
        
        return result;
    }
    
    /**
     * 用户登出
     */
    public void logout(String userId) {
        // 这里可以实现令牌黑名单逻辑
        // 由于JWT是无状态的，简单的登出只需要客户端删除令牌即可
        // 如果需要服务端控制，可以将令牌加入Redis黑名单
        
        // 记录登出日志
        // logService.recordLogout(userId);
    }
    
    /**
     * 修改密码
     */
    public void changePassword(String userId, String oldPassword, String newPassword) {
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 验证原密码
        if (!passwordEncoder.matches(oldPassword, user.getPasswordHash())) {
            throw new RuntimeException("原密码错误");
        }
        
        // 更新密码
        String newPasswordHash = passwordEncoder.encode(newPassword);
        userMapper.updatePassword(userId, newPasswordHash);
        
        // 记录密码修改的审计日志
        recordAuditLog("CHANGE_PASSWORD", "USER", userId, 
                      "用户修改密码成功", "SUCCESS", userId);
    }
    
    /**
     * 重置密码
     */
    public void resetPassword(String userId, String newPassword) {
        // 获取用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 更新密码
        String newPasswordHash = passwordEncoder.encode(newPassword);
        userMapper.updatePassword(userId, newPasswordHash);
        
        // 记录密码重置的审计日志
        recordAuditLog("RESET_PASSWORD", "USER", userId, 
                      "管理员重置用户密码", "SUCCESS", userId);
    }
    
    /**
     * 验证用户凭据
     */
    public boolean validateCredentials(String username, String password) {
        try {
            User user = userMapper.selectByUsername(username);
            if (user == null) {
                user = userMapper.selectByEmail(username);
            }
            
            if (user == null || user.getStatus() != 1) {
                return false;
            }
            
            return passwordEncoder.matches(password, user.getPasswordHash());
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 检查用户名是否可用
     */
    public boolean isUsernameAvailable(String username) {
        return !userMapper.existsByUsername(username, null);
    }
    
    /**
     * 检查邮箱是否可用
     */
    public boolean isEmailAvailable(String email) {
        return !userMapper.existsByEmail(email, null);
    }
    
    /**
     * 记录审计日志的辅助方法
     */
    private void recordAuditLog(String action, String resourceType, String resourceId, 
                               String description, String status, String userId) {
        try {
            AuditLogs auditLog = new AuditLogs();
            auditLog.setUserId(userId);
            auditLog.setOperationType(action);
            auditLog.setResourceType(resourceType);
            auditLog.setResourceId(resourceId);
            auditLog.setOperationDesc(description);
            auditLog.setOperationResult(status);
            auditLog.setOperationTime(LocalDateTime.now());
            
            // 获取用户信息
            if (StringUtils.hasText(userId)) {
                com.uniflow.entity.User user = userMapper.selectById(userId);
                if (user != null) {
                    auditLog.setUsername(user.getUsername());
                }
            }
            
            auditLogService.createAuditLog(auditLog);
        } catch (Exception e) {
            // 审计日志记录失败不应影响主业务流程，只记录错误日志
            System.err.println("记录审计日志失败: " + e.getMessage());
        }
    }
}